#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>

#include "type_routingtable.h"
#include "LBF_update.h"
#include "util.h"
#include "typecast_socket.h"
#include "typecast_timeout.h"

void ProcessLBFUpdate(char* buf)
{
    // Update the LBF from packet to table

    // Packet format:
    //    uint_8_t          num_of_groups
    //    uint_32_t         multicast_address_1
    //    bloom_filter_t    LBF_1
    //    uint_32_t         multicast_address_2
    //    bloom_filter_t    LBF_2
    //    ...

    int multicast_group_count;
    char * tail = buf;
    int routing_table_changed = 0; 
    multicast_group_count = (int) *tail;
    tail += sizeof(u_int8_t);

    printf("  Received LBF Update for %d multicast groups.\n", multicast_group_count);

    int i = 0;
    u_int32_t * grp_addr_ptr; 
    for (i = 0; i < multicast_group_count; i++)
    {
        u_int32_t multicast_group_addr;
        grp_addr_ptr = tail; 
        multicast_group_addr = ntohl(*grp_addr_ptr);
        tail += sizeof(u_int32_t);

        multicast_group_node * pMulticastGroupNode;
        pMulticastGroupNode = FindMulticastGroup(multicast_group_addr);
        if (!pMulticastGroupNode) { 
            InsertMulticastGroup(multicast_group_addr, tail);        
            tail += sizeof(bloom_filter_t);
            routing_table_changed = 1; 
        } else { 
            if (! is_bloom_filter_equvalent(pMulticastGroupNode->LBF, tail)) {                             
                copy_bloom_filter(pMulticastGroupNode->LBF, tail);
                routing_table_changed = 1; 
            }
            tail += sizeof(bloom_filter_t);
        }
                           
    }
    
    if (routing_table_changed) { 
        DumpTypeCastRoutingTable(stdout); 
        // send TA packet immediately
        typecast_send_TA();                                     
        // set the timer if the timer is not set yet
        start_ta_timer(); 
    }
    
}
